<?php
namespace HuoCore\Helper;
/**
 * 单商户： 每个应用端都持有相同的公私钥对；
 *          请求者用私钥加密数据发送数据，响应者用私钥解签，并用公钥进行数据
 *          有效性验签；合法后发送响应数据(私钥签名)
 */

class RSASign
{
    private $_pubKey;
    private $_priKey;
    private $_passphrase = '';

    //java 默认生成sign 方式
    const SIGN_DEFAULT_JAVA = OPENSSL_ALGO_MD5;

    /**
     * Sign constructor.
     */
    public function __construct()
    {
        $this->_pubKey = 'file://'.__DIR__.'/rsa/rsa_public_key.pem';
        $this->_priKey= 'file://'.__DIR__.'/rsa/rsa_private_key.pem';
    }

    /**
     * 用私钥加密数据
     * @param $data
     * @param int $mode
     * @return string
     * @internal param int $encryptMode
     */
    public function encryptWithPri($data, $mode = OPENSSL_PKCS1_PADDING)
    {
        $data = $this->getStringData($data);
        $res = openssl_get_privatekey($this->_priKey, $this->_passphrase);
        $bool = openssl_private_encrypt($data, $sign, $res, $mode);
        openssl_free_key($res);
        if($bool){
            return base64_encode($sign);
        }else{
            return $data;
        }
    }

    /**
     *  用私钥签名
     *
     * @param $data
     * @param int $alg 签名方法
     * @return string
     */
    public function signWithPri($data, $alg = OPENSSL_ALGO_SHA1)
    {
        $data = $this->getStringData($data);
        $priId = openssl_pkey_get_private($this->_priKey);
        $bool = openssl_sign($data, $sign, $priId, $alg);
        if($bool){
            return base64_encode($sign);
        }else{
            return $data;
        }
    }

    /**
     * 用公钥加密数据
     *
     * @param $data
     * @param int $mode
     * @return string
     */
    public function encryptWithPub($data, $mode = OPENSSL_PKCS1_PADDING)
    {
        $data = $this->getStringData($data);
        $res = openssl_get_publickey($this->_pubKey);
        $bool = openssl_public_encrypt($data, $sign, $res, $mode);
        openssl_free_key($res);
        if($bool){
            return base64_encode($sign);
        }else{
            return $data;
        }
    }

    /**
     * 私钥解密数据
     *
     * @param $sign
     * @param int $mode
     * @return string
     */
    public function decryptWithPri($sign, $mode = OPENSSL_PKCS1_PADDING)
    {
        $sign = base64_decode($sign);
        $res = openssl_get_privatekey($this->_priKey);
        $bool = openssl_private_decrypt($sign, $data, $res, $mode);
        openssl_free_key($res);
        if($bool){
            return $data;
        }else{
            return '';
        }
    }


    /**
     * 私钥解密数据
     *
     * @param $sign
     * @return string
     */
    public function decryptWithPriFenDuan($sign)
    {
        $sign = base64_decode($sign);
        $res = openssl_get_privatekey($this->_priKey);

        $result  = '';
        for($i = 0; $i < strlen($sign)/128; $i++  ) {
            $data = substr($sign, $i * 128, 128);
            openssl_private_decrypt($data, $decrypt, $res);
            $result .= $decrypt;
        }
        openssl_free_key($res);
        return $result;
    }

    /**
     * 公钥解密数据
     *
     * @param $sign
     * @param int $mode
     * @return string
     */
    public function decryptWithPub($sign, $mode = OPENSSL_PKCS1_PADDING)
    {
        $sign = base64_decode($sign);
        $res = openssl_get_publickey($this->_pubKey);
        $bool = openssl_public_decrypt($sign, $data, $res, $mode);
        openssl_free_key($res);
        if($bool){
            return $data;
        }else{
            return '';
        }
    }

    /**
     *  验签
     *
     * @param $data
     * @param string $sign 经base64的私钥签名
     * @param int $alg 签名方法
     * @return bool
     */
    public function verifySign($data, $sign, $alg = OPENSSL_ALGO_SHA1)
    {
        $sign = base64_decode($sign);
        $res = openssl_get_publickey($this->_pubKey);
        $verify = openssl_verify($data, $sign, $res, $alg);
        openssl_free_key($res);
        if($verify == 1){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 数组转字符串,带自定义连接符号
     *
     * @param $data
     * @param string $glue 字符串连接符
     * @return string
     */
    public function getStringData($data, $glue = '&')
    {
        if(is_array($data)){
            $data = implode($glue, $data);
        }
        return $data;
    }

}
